#region --- License & Copyright Notice ---

/*

ID3.NET ID3 tag implementation library

Copyright (c) 2007 Ananth B.
All rights reserved.

The contents of this file are made available under the terms of the
Eclipse Public License v1.0 (the "License") which accompanies this
distribution, and is available at the following URL:
http://opensource.org/licenses/eclipse-1.0.txt

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.

By using this software in any fashion, you are agreeing to be bound by the
terms of the License.

*/

#endregion

using System.Collections.Generic;

namespace Id3.Net.Samples.ListMusic
{
    internal sealed class CommandLineParser
    {
        private string[] _args;
        private string _errorMessage;
        private string _format = "{album} - {title}";
        private string[] _groupByList = new string[] { "artist" };

        internal CommandLineParser(string[] args)
        {
            _args = args;
        }

        internal bool Parse()
        {
            if (_args.Length == 0)
                return true;

            List<CommandLineArgument> arguments = new List<CommandLineArgument>(_args.Length);
            foreach (string arg in _args)
                arguments.Add(CommandLineParser.ParseArgument(arg.ToLowerInvariant()));

            List<string> groupByList = new List<string>(arguments.Count);
            foreach (CommandLineArgument argument in arguments)
            {
                if (argument.SwitchName == "groupby")
                {
                    if (!CommandLineParser.IsValidId3Property(argument.ParameterName))
                    {
                        _errorMessage = "Invalid ID3 property specified: " + argument.ParameterName;
                        return false;
                    }
                    if (groupByList.Contains(argument.ParameterName))
                    {
                        _errorMessage = "You've already specified the ID3 property " + argument.ParameterName;
                        return false;
                    }
                    groupByList.Add(argument.ParameterName);
                    continue;
                }

                if (argument.SwitchName != null)
                {
                    _errorMessage = "Invalid switch " + argument.SwitchName;
                    return false;
                }

                _format = argument.ParameterName;
            }

            if (groupByList.Count > 0)
                _groupByList = groupByList.ToArray();

            return true;
        }

        #region Properties

        internal string ErrorMessage
        {
            get
            {
                return _errorMessage;
            }
        }

        internal string Format
        {
            get
            {
                return _format;
            }
        }

        internal string[] GroupByList
        {
            get
            {
                return _groupByList;
            }
        }

        #endregion

        #region Private static helper methods

        private static bool IsValidId3Property(string propertyName)
        {
            return propertyName == "artist" ||
                propertyName == "album" ||
                propertyName == "title" ||
                propertyName == "track" ||
                propertyName == "year" ||
                propertyName == "genre";
        }

        private static CommandLineArgument ParseArgument(string arg)
        {
            if (!arg.StartsWith("/") || !arg.StartsWith("-"))
                return new CommandLineArgument(null, arg);

            int switchEndIndex = arg.IndexOf(':', 1);
            if (switchEndIndex < 0)
                return new CommandLineArgument(arg.Substring(1), null);

            string switchName = arg.Substring(1, switchEndIndex - 1);
            string parameterName = arg.Substring(switchEndIndex + 1);
            return new CommandLineArgument(switchName, parameterName);
        }

        #endregion
    }

    internal sealed class CommandLineArgument
    {
        private readonly string _switchName;
        private readonly string _parameterName;

        internal CommandLineArgument(string switchName, string parameterName)
        {
            _switchName = switchName;
            _parameterName = parameterName;
        }

        internal string ParameterName
        {
            get
            {
                return _parameterName;
            }
        }

        internal string SwitchName
        {
            get
            {
                return _switchName;
            }
        }
    }
}
